﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.IO;

namespace WiimoteMap
{
    public partial class Main : Form
    {
        WiimoteLib.Wiimote wiimote;
        float joyTreshhold = 0.14f;
        const string mapFilePath = "maps.txt";

        Dictionary<WiimoteButtons, Keyboard.Keymaps> KeyMap = new Dictionary<WiimoteButtons, Keyboard.Keymaps>();


        enum WiimoteButtons
        {
            A,
            B,
            Minus,
            Plus,
            Home,
            One,
            Two,
            Up,
            Down,
            Left,
            Right,
            C,
            Z,
            NunUp,
            NunDown,
            NunLeft,
            NunRight
        }


        public Main()
        {
            InitializeComponent();

            Icon = WiimoteMap.Properties.Resources.wiicontroller;

            PopulateMapBox();
            LoadKeymaps();

            wiimote = new WiimoteLib.Wiimote();
            wiimote.WiimoteChanged += new EventHandler<WiimoteLib.WiimoteChangedEventArgs>(wiimote_WiimoteChanged);
            wiimote.SetReportType(WiimoteLib.InputReport.Buttons, true);
            wiimote.Connect();
            
        }

        void PopulateMapBox()
        {
            textBoxWiibuttons.Lines = Enum.GetNames(typeof(WiimoteButtons));
        }

        void PopulateValueBox()
        {
            List<string> values = new List<string>();

            foreach (KeyValuePair<WiimoteButtons, Keyboard.Keymaps> pairs in KeyMap)
            {
                values.Add(pairs.Value.ToString());
            }

            textBoxMaps.Lines = values.ToArray();
        }

        void LoadDefaultKeymaps()
        {
            KeyMap.Clear();
            KeyMap.Add(WiimoteButtons.A, Keyboard.Keymaps.A);
            KeyMap.Add(WiimoteButtons.B, Keyboard.Keymaps.B);
            KeyMap.Add(WiimoteButtons.Minus, Keyboard.Keymaps.C);
            KeyMap.Add(WiimoteButtons.Plus, Keyboard.Keymaps.D);
            KeyMap.Add(WiimoteButtons.Home, Keyboard.Keymaps.E);
            KeyMap.Add(WiimoteButtons.One, Keyboard.Keymaps.F);
            KeyMap.Add(WiimoteButtons.Two, Keyboard.Keymaps.G);
            KeyMap.Add(WiimoteButtons.Up, Keyboard.Keymaps.H);
            KeyMap.Add(WiimoteButtons.Down, Keyboard.Keymaps.I);
            KeyMap.Add(WiimoteButtons.Left, Keyboard.Keymaps.J);
            KeyMap.Add(WiimoteButtons.Right, Keyboard.Keymaps.K);
            KeyMap.Add(WiimoteButtons.C, Keyboard.Keymaps.L);
            KeyMap.Add(WiimoteButtons.Z, Keyboard.Keymaps.M);
            KeyMap.Add(WiimoteButtons.NunUp, Keyboard.Keymaps.N);
            KeyMap.Add(WiimoteButtons.NunDown, Keyboard.Keymaps.O);
            KeyMap.Add(WiimoteButtons.NunLeft, Keyboard.Keymaps.P);
            KeyMap.Add(WiimoteButtons.NunRight, Keyboard.Keymaps.Q);

            PopulateValueBox();

        }

        void LoadKeymaps()
        {
            try
            {
                KeyMap.Clear();

                foreach (string pair in File.ReadAllLines(mapFilePath))
                {
                    string[] splitPair = pair.Split('=');
                    KeyMap.Add(
                        (WiimoteButtons)Enum.Parse(typeof(WiimoteButtons), splitPair[0]),
                        (Keyboard.Keymaps)Enum.Parse(typeof(Keyboard.Keymaps), splitPair[1]));

                }

                PopulateValueBox();
            }
            catch
            {
                LoadDefaultKeymaps();
            }



        }

        void SaveKeymaps()
        {
            List<string> pairStrings = new List<string>();

            foreach (KeyValuePair<WiimoteButtons, Keyboard.Keymaps> pair in KeyMap)
            {
                pairStrings.Add(pair.Key.ToString() + "=" + pair.Value.ToString());
            }

            File.WriteAllText(mapFilePath, string.Join(Environment.NewLine, pairStrings.ToArray()));
        }

        WiimoteLib.ButtonState previousState = new WiimoteLib.ButtonState();
        WiimoteLib.NunchukState previousNunchuckState = new WiimoteLib.NunchukState();
        bool xPos = false;
        bool xNeg = false;
        bool yPos = false;
        bool yNeg = false;

        void wiimote_WiimoteChanged(object sender, WiimoteLib.WiimoteChangedEventArgs e)
        {

            if ((e.WiimoteState.NunchukState.Joystick.X > joyTreshhold) != xPos)
            {
                Keyboard.SendKey(KeyMap[WiimoteButtons.NunRight], !xPos);
                xPos = !xPos;
            }

            else if ((e.WiimoteState.NunchukState.Joystick.X < -joyTreshhold) != xNeg)
            {
                Keyboard.SendKey(KeyMap[WiimoteButtons.NunLeft], !xNeg);
                xNeg = !xNeg;
            }

            if ((e.WiimoteState.NunchukState.Joystick.Y > joyTreshhold) != yPos)
            {
                Keyboard.SendKey(KeyMap[WiimoteButtons.NunUp], !yPos);
                yPos = !yPos;
            }

            else if ((e.WiimoteState.NunchukState.Joystick.Y < -joyTreshhold) != yNeg)
            {
                Keyboard.SendKey(KeyMap[WiimoteButtons.NunDown], !yNeg);
                yNeg = !yNeg;
            }

            if (e.WiimoteState.NunchukState.C != previousNunchuckState.C)
            {
                Keyboard.SendKey(KeyMap[WiimoteButtons.C], e.WiimoteState.NunchukState.C);
            }

            if (e.WiimoteState.NunchukState.Z != previousNunchuckState.Z)
            {
                Keyboard.SendKey(KeyMap[WiimoteButtons.Z], e.WiimoteState.NunchukState.Z);
            }

            if (e.WiimoteState.ButtonState.A != previousState.A)
            {
                Keyboard.SendKey(KeyMap[WiimoteButtons.A], e.WiimoteState.ButtonState.A);
            }

            if (e.WiimoteState.ButtonState.B != previousState.B)
            {
                Keyboard.SendKey(KeyMap[WiimoteButtons.B], e.WiimoteState.ButtonState.B);
            }

            if (e.WiimoteState.ButtonState.Home != previousState.Home)
            {
                Keyboard.SendKey(KeyMap[WiimoteButtons.Home], e.WiimoteState.ButtonState.Home);
            }

            if (e.WiimoteState.ButtonState.Minus != previousState.Minus)
            {
                Keyboard.SendKey(KeyMap[WiimoteButtons.Minus], e.WiimoteState.ButtonState.Minus);
            }

            if (e.WiimoteState.ButtonState.Plus != previousState.Plus)
            {
                Keyboard.SendKey(KeyMap[WiimoteButtons.Plus], e.WiimoteState.ButtonState.Plus);
            }

            if (e.WiimoteState.ButtonState.One != previousState.One)
            {
                Keyboard.SendKey(KeyMap[WiimoteButtons.One], e.WiimoteState.ButtonState.One);
            }

            if (e.WiimoteState.ButtonState.Two != previousState.Two)
            {
                Keyboard.SendKey(KeyMap[WiimoteButtons.Two], e.WiimoteState.ButtonState.Two);
            }

            if (e.WiimoteState.ButtonState.Up != previousState.Up)
            {
                Keyboard.SendKey(KeyMap[WiimoteButtons.Up], e.WiimoteState.ButtonState.Up);
            }

            if (e.WiimoteState.ButtonState.Right != previousState.Right)
            {
                Keyboard.SendKey(KeyMap[WiimoteButtons.Right], e.WiimoteState.ButtonState.Right);
            }

            if (e.WiimoteState.ButtonState.Down != previousState.Down)
            {
                Keyboard.SendKey(KeyMap[WiimoteButtons.Down], e.WiimoteState.ButtonState.Down);
            }

            if (e.WiimoteState.ButtonState.Left != previousState.Left)
            {
                Keyboard.SendKey(KeyMap[WiimoteButtons.Left], e.WiimoteState.ButtonState.Left);
            }

            previousState = e.WiimoteState.ButtonState;
            previousNunchuckState = e.WiimoteState.NunchukState;
        }

        class Keyboard
        {
            [DllImport("user32.dll")]
            public static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, uint dwExtraInfo);

            public enum Keymaps : byte
            {
                A = 65,
                B = 66,
                C = 67,
                D = 68,
                E = 69,
                F = 70,
                G = 71,
                H = 72,
                I = 73,
                J = 74,
                K = 75,
                L = 76,
                M = 77,
                N = 78,
                O = 79,
                P = 80,
                Q = 81,
                R = 82,
                S = 83,
                T = 84,
                U = 85,
                V = 86,
                W = 87,
                X = 88,
                Y = 89,
                Z = 90
            };

            public static void SendKey(Keymaps key , bool down)
            {
                keybd_event((byte)key, 0, (uint)(down ? 0 : 2), 0);
            }

        }

        private void textBoxMaps_KeyPress(object sender, KeyPressEventArgs e)
        {
            int CurrentLine = textBoxMaps.GetLineFromCharIndex(textBoxMaps.SelectionStart);

            if (Enum.GetNames(typeof(Keyboard.Keymaps)).Contains(e.KeyChar.ToString().ToUpper()))
            {

                KeyMap[(WiimoteButtons)Enum.Parse(typeof(WiimoteButtons), textBoxWiibuttons.Lines[CurrentLine])] = 
                    (Keyboard.Keymaps)Enum.Parse(typeof(Keyboard.Keymaps), e.KeyChar.ToString().ToUpper());

                string[] lines = textBoxMaps.Lines;      
                lines[CurrentLine] = e.KeyChar.ToString().ToUpper();
                textBoxMaps.Lines = lines;          

            }

            int charIndex = 0;

            for (int i = 0; i < CurrentLine; i++)
            {
                charIndex += textBoxMaps.Lines[i].Length + 2;
            }

            if (charIndex == textBoxMaps.Text.Length - 1) charIndex = -3;

            textBoxMaps.SelectionStart = charIndex + 3;
            textBoxMaps.SelectionLength = 0;
            textBoxMaps.ScrollToCaret();

            e.Handled = true;
        }

        private void buttonLoad_Click(object sender, EventArgs e)
        {
            LoadKeymaps();
        }

        private void buttonDefault_Click(object sender, EventArgs e)
        {
            LoadDefaultKeymaps();
        }

        private void buttonSave_Click(object sender, EventArgs e)
        {
            SaveKeymaps();
        }


    }
}
